home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BBS Toolkit
/
BBS Toolkit.iso
/
maximus
/
mxms_161.zip
/
MAXMAIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-04
|
20KB
|
520 lines
/****************************************************************************/
/* */
/* Maxmail : By Craig Derouen */
/* October 10,1990 */
/* Maximus ARCHIVE Mail Xfer Utility */
/* */
/****************************************************************************/
/* Version History:
Version 1.0 12-23-90 First release to public
Version 1.5 02-24-91 Changed WRITE file ptr casting, altered activity divit.
Alter display of hi message numbers to insure unsigned
values.
Fixed weird problems with lastread ptr updating in
LOCAL message areas thanks to John Musslewhite.
Allow default for Packing and Protocol questions on
configure menu.
Allow NON-Swap mode for exec'ing externals
Alternate directory for creating and packing up
archive mail
Message text file will carry bbs name like ARC file
Rework fossil code, eliminate external lib.
OPUS style and MAX style barricaded areas support
Support for non-numeric message areas
Color support
Sysop/user chat mode
Hangup after download, DTR or AT command
Signon bulletin file option
Check disk space before running.
Progress message for scanning areas
Allow message ptr reset to 1 in non-echomail areas
Version 1.52 04-17-91 Add count for # of times called today,plus control
for sysop to limit it.
Version 1.60 06-08-91 Add Sysop local menu
Add daily message pack count and sysop control
Adjust RCV flag for messages to specific user in
local msg areas.
Allow packer execution to be redirected to COM1,2,3,4
Fix temp dir problems
Fix problems with filesize testing/time at download
prompt.
Qwk support!
Add newfiles list include option
If xfer program error, return to menu instead of
aborting back to MaxMail, allowing user to retry
Add user configurable max pack count per message area
for QWK packets.
Add hangup after download countdown option
Input REP packets from prompt in local mode..
Add configuration menu
Add forced messages areas
Support QWK reader add/del msg area functions
Version 1.61 07-18-91 Fix FOSSIL hardware handshaking.
Fix himsg adjust for private messages.
Add ECHOTOSS log support.
Ignore msg upload to READ_ONLY area.
Fixup PASCAL calling style.
Convert FOSSIL char out to prevent lockup.
*/
#define MAIN 1
#include "MaxMail.h"
extern int Bells;
int secret = FALSE;
void main(int argc,char **argv)
{
int x,z;
unsigned y;
unsigned long count;
struct stat fbuf;
time_t thistime;
struct tm *newtime;
struct _yell *yellptr;
union REGS r,r1;
struct find_t fileinfo;
/* Parse out the drive and dir where maxmail is located */
_splitpath(argv[0],hdrive,hdir,temp,temp1); /* Ignore name and extension */
IsLocal = TRUE;
TimeAdjust = FALSE;
msg_update = TRUE;
packer_del = TRUE;
HaveUpl = FALSE;
WatchDog = FALSE;
ChatOk = FALSE;
YellOn= FALSE;
MaxDaily = 0; /* Defaults, allow infinite calls per day */
SwapMode = -1;
SysopMode = FALSE;
newuser = FALSE;
HangupMode = 0;
Hangup = 0; /* Disable it */
MaxMsgs = 400; /* Maximum number of messages to parse */
Task = 0; /* If > 0, Multiuser mode */
strcpy(MCfgFile,"MaxMail.cfg");
strcpy(LastUse,"Lastuser.bbs");
strcpy(PrmFile,"Max.Prm");
strcpy(CfgFile,"MaxMail.usr");
strcpy(TxtFile,"MaxMsgs.txt");
strcpy(StatName,"MsgStats");
strcpy(SumFile,"Summary");
Exitcode = 0;
Pport = -1;
for (x = 1; x < argc; x++) { /* Parse out command line */
if (argv[x][0] == '-' || argv[x][0] == '/') {
y = toupper(argv[x][1]); /* Argument switch */
switch (y) {
case 'A': /* Adjust time online */
TimeAdjust = TRUE;
break;
case 'C': /* MaxMail configfile */
strcpy(CfgFile,argv[x]+2);
break;
case 'D': /* Don't swap */
SwapMode = FALSE;
break;
case 'L': /* Force Local mode */
IsLocal = 2;
break;
case 'N': /* Don't delete packed file */
packer_del = FALSE;
break;
case 'O': /* Port selection */
Pport = argv[x][2] - '0';
break;
case 'P': /* Parm file */
strcpy(PrmFile,argv[x]+2);
break;
case 'S': /* Enable Sysop mode */
SysopMode = TRUE;
IsLocal = 2;
break;
case 'T': /* Task number */
Task = argv[x][2] - '0';
sprintf(LastUse,"Lastus%02x.bbs",Task);
break;
case 'U': /* Turn off lastread update */
msg_update = FALSE;
break;
case 'Z': /* Show parms */
secret = TRUE;
show_opts();
break;
case '?': /* Show parms */
show_opts();
break;
}
}
else { /* Only non-switch argument specifies the Maxmail config file */
strcpy(MCfgFile,argv[x]);
}
}
init();
if (Pport == -1)
Pport = prm.com_port;
if (!SysopMode) {
if (SwapMode == -1)
SwapMode = TRUE; /* Default to swapping */
/* Open the last userfile. Without it, we can't do a thing! */
x = sopen(LastUse,O_RDONLY | O_BINARY,SH_DENYNO,S_IREAD);
if (x == -1)
aborterror(FILEOPEN,"Missing Lastuse file");
y = read(x,&LastUser,sizeof(struct _usr));
user_slen = (LastUser.struct_len ? LastUser.struct_len * 20 : 180);
lseek(x,0L,SEEK_SET);
y = read(x,&LastUser,user_slen);
if (y < (unsigned) user_slen) { /* Humm couldnt read all of file! */
close(x);
aborterror(FILEOPEN,"Error reading LastUse file");
}
close(x); /* We only need the file for the structure info */
strcpy(UserName,LastUser.name);
if (IsLocal < 2)
/* IsLocal = LastUser.flag == 0 ? TRUE : FALSE; */
IsLocal = FALSE;
if (!IsLocal) {
if(!FossilInit())
aborterror(FILEOPEN,"Couldn't open FOSSIL");
}
/* Now Compute the maximum messages caller can have for this run
based upon time remaining and baud rate. This is really a
ROUGH guess and I will polish it in time! */
count = get_kminute(); /* Fetch # of Kilobytes per minute at current baud */
count *= LastUser.timeremaining; /* Total # of Kbytes we can download */
/* Assume message is average of 500 bytes when packed */
count /= 500;
MaxMsgs = ((MaxMsgs > (unsigned) count) && LastUser.flag) ? (unsigned) count : MaxMsgs;
UserCfgnum = 0; /* Startup */
if(stat(CfgFile,&fbuf) == 0 ) /* Does file exist? */
x = sopen(CfgFile,O_RDWR | O_BINARY,SH_DENYNO,S_IREAD);
else x = sopen(CfgFile,O_RDWR | O_BINARY | O_CREAT,SH_DENYNO,S_IWRITE);
if (x == -1)
aborterror(FILEOPEN,"Error opening/creating User config file");
UserCfgnum = find_config(x,LastUser.name,&USERCFG);
if (UserCfgnum < 0) { /* Couldn't be found */
newuser_help(); /* Display a file to the new user */
newuser = TRUE;
memset(&USERCFG,0,sizeof(struct user_cfg));
USERCFG.flags |= USRCFG_UPD; /* Force the user to update his configuration */
memcpy(USERCFG.name,LastUser.name,36);
UserCfgnum = find_blconfig(x); /* Look for an empty slot */
if (UserCfgnum < 0) /* Couldn't be found */
UserCfgnum = new_user(x);
}
close(x); /* We only need the file for the structure info */
afile = _fsopen(PRM(adat_name),"rb",SH_DENYNO);
if (afile == NULL)
aborterror(FILEOPEN,"Missing AREA.DAT file");
fread(&AREA,sizeof(struct _area),1,afile);
astrlen = AREA.struct_len;
find_class();
if(fidomsg_init())
aborterror(BADALLOC,NULL);
/* Check disk space before really starting up things */
if (tdir[0])
strcpy(temp,tdir);
else strcpy(temp,PRM(sys_path));
signon(); /* Sign on message */
/* Extract drive from pathname */
r.h.dl = (unsigned char) (toupper(temp[0]) - 0x40); /* A=1,B=2,etc */
r.h.ah = 0x36; /* DOS get free space call */
intdos(&r,&r1);
if (r1.x.ax == 0xffff) { /* Invalid temp drive? */
strcpy(temp,PRM(sys_path)); /* Try Max root drive instead */
r.h.dl = (unsigned char) (temp[0] - 0x40); /* A=1,B=2,etc */
intdos(&r,&r1);
if (r1.x.ax == 0xffff) /* We are really in trouble now! */
aborterror(FILECREATE,"Invalid drive specified");
}
count = r1.x.cx; /* Bytes per sector */
count *= r1.x.ax; /* # of sectors per cluster */
count *= r1.x.bx; /* # of available clusters = total byte space */
if (count < 512000 ) { /* Look for about 500K free */
setcolor(TextAttr[ATTN_TEXT]);
strout("Sorry but there is not enough disk space left on this drive\r\n");
strout(" to run MaxMail. Notify the sysop....\r\n");
logit("Working drive has too low disk space",'!');
deinit(2);
}
if (USERCFG.flags & (USRCFG_UPD | USRCFG_FUPD | USRCFG_MSGUPD))
getconfig();
else {
strout("\r\nScanning selected message areas. Hang on....");
y = USERCFG.totareas;
build_areas(FALSE,TRUE);
if (USERCFG.totareas != y && USERCFG.totareas) {
USERCFG.flags |= USRCFG_MSGUPD;
getconfig();
}
if (USERCFG.totpackers != (unsigned) totpackers) {
setcolor(TextAttr[ATTN_TEXT]);
strout("\r\nMessage packer types have changed since your last call.");
get_packer(TRUE);
}
if (USERCFG.totprotos != (unsigned) totprotocols) {
setcolor(TextAttr[ATTN_TEXT]);
strout("\r\nDownload protocols have changed since your last call.");
get_proto(TRUE);
}
}
/* Determine if yell can be enabled */
Bells = 0;
if (prm.noise_ok) {
time(&thistime);
newtime = localtime(&thistime);
yellptr = NULL;
for (z = 0; z < MAX_YELL; z++) { /* Scan yell sched array */
if (prm.yell[z].weekday == (unsigned char) newtime->tm_wday ) {
yellptr = &prm.yell[z]; /* Fetch current yell event */
break;
}
}
if (yellptr && yellptr->weekday) { /* It is valid */
if (newtime->tm_hour >= (int) yellptr->start_hour) {
if (newtime->tm_hour == (int) yellptr->start_hour) {
if (newtime->tm_min <= (int) yellptr->end_min) {
YellOn = TRUE;
Bells = yellptr->bells;
}
}
else {
if (newtime->tm_hour == (int) yellptr->end_hour) {
if (newtime->tm_min <= (int) yellptr->end_min) {
YellOn = TRUE;
Bells = yellptr->bells;
}
}
else if (newtime->tm_hour < (int) yellptr->end_hour) {
YellOn = TRUE;
Bells = yellptr->bells;
}
}
}
}
}
menu();
strout("\r\n\r\n");
if (*SignOff) {
strout(SignOff);
strout("\r\n");
}
if (totmsgs)
update_msgs(); /* Update the lastread pointers */
if (!IsLocal) {
if (Hangup < 1)
strout("Heading back to Maximus. Please wait a sec....\r\n");
else { /* Hang up the user */
setcolor(TextAttr[HILITE_TEXT]);
strout("Hanging you up now!\r\n");
setcolor(TextAttr[STD_TEXT]);
strout("Press [H]ang up for quick log off or [ENTER] to abort ..... ");
setcolor(TextAttr[MENU_KEY]);
FossPurgeBuff(TRUE);
for (z = 10; z >= 0; z--) {
sprintf(temp,"\b\b%02d",z);
strout(temp);
FossSendStr("\07");
delay_s(1);
if((y = FossGetCh()) != 0xFFFF) {
y &= 0x00ff;
if (y == 'h' || y == 'H') {
z = 0; /* Force hangup */
break;
}
else if (y == '\r') {
z = 1;
break;
}
}
}
if (z <= 0) {
setcolor(TextAttr[STD_TEXT]);
sprintf(temp,"\r\n\tSo long %s .......\r\n",LastUser.name);
strout(temp);
delay_s(2);
logit("User requested hangup after download",'#');
FossFlow(0); /* Turn Control-S off */
FossPurgeBuff(FALSE); /* Output buffer */
while (!(FossMdmStatus() & 0x4000)); /* Check output buffer */
if (HangupMode == 1) { /* Use HAYES method */
z = 0; /* Deadlock counter */
do
{
FossSendCh('+'); /* Get modem's attention */
delay_ms(400);
FossSendCh('+'); /* Get modem's attention */
delay_ms(400);
FossSendCh('+'); /* Get modem's attention */
delay_s(2);
FossSendStr("ATH0\r\n"); /* Hayes AT command to hang up */
delay_s(1);
z++;
}
while ((FossMdmStatus() & 128) && z < 10); /* Check carrier */
}
else { /* Use DTR method */
delay_ms(500);
FossDtr(FALSE); /* Lower DTR */
delay_ms(1500); /* 1.5 seconds */
FossDtr(TRUE); /* Raise DTR */
}
deinit(5); /* Leave MaxMail and tell caller user hangup */
}
else { /* User aborted auto hangup */
setcolor(TextAttr[STD_TEXT]);
strout("\r\nHeading back to Maximus. Please wait a sec....\r\n");
logit("User aborted auto hangup after download",'#');
}
}
}
}
else { /* Special local sysop maintainence mode */
sprintf(temp,"Begin, v%2.2f",Version);
logit(temp,'+');
strcpy(temp1,"Local sysop maintainence mode");
logit(temp1,':');
strout("MaxMail - a MAXIMUS message utility by Craig Derouen\r\n");
printf("\t*** Version %2.2f ***\r\n",Version);
printf("Last compiled: %s\n",__TIMESTAMP__);
strout(temp1);
strout("\n");
if (!parmread) {
if(read_prm(PrmFile) < 0)
aborterror(FILEOPEN,"Error opening PRM file!\r\n");
}
afile = _fsopen(PRM(adat_name),"rb",SH_DENYNO);
if (afile == NULL)
aborterror(FILEOPEN,"Missing AREA.DAT file");
fread(&AREA,sizeof(struct _area),1,afile);
astrlen = AREA.struct_len;
/* We still have to read the lastuse file, but just to get length for
later. So just look for ANY lastuser file. */
if(_dos_findfirst("Lastus??.bbs",_A_NORMAL,&fileinfo) == 0) {
strcpy(LastUse,fileinfo.name);
x = sopen(LastUse,O_RDONLY | O_BINARY,SH_DENYNO,S_IREAD);
if (x == -1)
aborterror(FILEOPEN,"Missing Lastuse file");
read(x,&LastUser,sizeof(struct _usr));
user_slen = (LastUser.struct_len ? LastUser.struct_len * 20 : 180);
close(x);
}
else { /* Create a fake one */
LastUser.ansi = TRUE;
LastUser.avatar = FALSE;
}
strcpy(LastUser.name,"Local Sysop"); /* Special mode */
strcpy(UserName,"Local Sysop"); /* Special mode */
Sys_menu();
packer_del = TRUE;
TimeAdjust = FALSE;
deinit(0);
}
deinit(Exitcode);
}
/* Display version and compiler time to user. Put this function here
in this module since TIMESTAMP checks only this module for date */
void _pascal ShowVers(void)
{
struct tm *newtime;
time_t aclock;
setcolor(TextAttr[STD_TEXT]);
sprintf(temp,"MaxMail, Version %2.2f, By Craig Derouen\r\n",Version);
strout(temp);
sprintf(temp,"Running under DOS %d.%d\r\n",_osmajor,_osminor);
strout(temp);
setcolor(TextAttr[HILITE_TEXT]);
sprintf(temp,"Program was last compiled: %s\r\n",__TIMESTAMP__);
strout(temp);
setcolor(TextAttr[MENU_KEY]);
sprintf(temp,"Remaining heap: %u bytes\r\n",_memavl());
strout(temp);
time(&aclock);
newtime = localtime(&aclock);
setcolor(TextAttr[STD_TEXT]);
sprintf(temp,"Current date and time are: %s\r\n",asctime(newtime));
strout(temp);
}
void _pascal show_opts(void)
{
printf("\nMaxmail Version: %2.2f by Craig Derouen\n",Version);
printf("Last compiled: %s\n",__TIMESTAMP__);
if (secret) {
printf("\t\a\aWaka! Waka! Waka! Author's secret function!\n");
printf("\tRemaining heap: %u bytes\n",_memavl());
printf("Since you are NOT the author, I am aborting...\n\n");
}
printf("Command line options:\n");
printf("\t /A: Adjust for time user is online\n");
printf("\t /C: Specify alt Maxmail USER config file\n");
printf("\t /D: Turn off SWAPPING mode for external programs\n");
printf("\t /L: Turns on local mode. No fossil handling\n");
printf("\t /N: Don't delete archive pack on exit (Use with local mode)\n");
printf("\t /Ox: Where x is optional FOSSIL port number (0=Com1,1=Com2,etc)\n");
printf("\t /P: Specify alt Max.prm file\n");
printf("\t /T: Specify Task number. Tells Maxmail we are running multiuser\n");
printf("\t /S: Sysop local maintainence mode\n");
printf("\t /U: Don't update LASTREAD message pointers\n");
printf("\t {Filename} use this file as alt Maxmail.cfg file\n");
exit(0);
}